import os
import cv2 as cv    
import numpy as np  

# 固定处理 hanzi1.jpg 文件
IMAGE_FILENAME = r'C:\Users\Administrator\Pictures\hanzi1.jpg'
CHAR_DIR = 'chars'  # 固定保存目录
PROCESS_DIR = 'process_steps'  # 保存处理步骤的目录

def main():
    script_dir = os.path.dirname(os.path.abspath(__file__))
    image_path = os.path.join(script_dir, IMAGE_FILENAME)
    
    # 读取图像（灰度模式）
    img = cv.imread(image_path, 0)
    if img is None:
        print(f"错误：无法读取文件 {IMAGE_FILENAME}")
        return
    
    print(f"成功读取图像：{IMAGE_FILENAME}，尺寸：{img.shape}")
    os.makedirs(CHAR_DIR, exist_ok=True)
    os.makedirs(PROCESS_DIR, exist_ok=True)  # 创建保存处理步骤的目录
    process_image(img)

def process_image(img):
    height, width = img.shape  # 获取图像尺寸
    blur = cv.GaussianBlur(img, (5, 5), 0)
    _, th = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
    th1_inv = 255 - th

    # 腐蚀、膨胀、闭运算等预处理保持不变
    kernel1 = np.ones((3, 3), np.uint8)
    eroded_img = cv.erode(th1_inv, kernel1, iterations=4)
    
    kernel2 = cv.getStructuringElement(cv.MORPH_CROSS, (4, 4)).astype(np.uint8)
    dilated_img = cv.dilate(eroded_img, kernel2, iterations=8)
    median_blurred = cv.medianBlur(dilated_img, 3)
    
    kernel3 = np.ones((5, 5), np.uint8)
    closed_img = cv.morphologyEx(dilated_img, cv.MORPH_CLOSE, kernel3, iterations=25)

    # Canny 边缘检测
    img_blur = cv.GaussianBlur(closed_img, (3, 3), 0)
    canny = cv.Canny(img_blur, 100, 200)
    contours, _ = cv.findContours(canny, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    valid_contours = []
    for c in contours:
        perimeter = cv.arcLength(c, True)
        if 350 < perimeter < 600:
            valid_contours.append(c)
    
    print(f"检测到 {len(valid_contours)} 个有效字符轮廓")
    
    for i, c in enumerate(valid_contours):
        x, y, w, h = cv.boundingRect(c)
        
        # **关键修复：添加边界限制**
        margin = 15  # 边距大小
        x_min = max(0, x - margin)       # 左边界不小于0
        y_min = max(0, y - margin)       # 上边界不小于0
        x_max = min(width, x + w + margin)  # 右边界不超过图像宽度
        y_max = min(height, y + h + margin) # 下边界不超过图像高度
        
        # 确保切割区域有效（宽度和高度大于0）
        if (x_max - x_min) <= 0 or (y_max - y_min) <= 0:
            print(f"警告：轮廓 {i+1} 坐标越界，跳过保存")
            continue
        
        roi = th[y_min:y_max, x_min:x_max]
        save_path = os.path.join(CHAR_DIR, f'char_{i+1}.jpg')
        
        if cv.imwrite(save_path, roi):
            print(f"成功保存字符 {i+1} 到 {save_path}")
        else:
            print(f"错误：无法保存字符 {i+1} 到 {save_path}")

    # 保存每一步的图像
    save_step_image(img, "original", PROCESS_DIR)
    save_step_image(blur, "blur", PROCESS_DIR)
    save_step_image(th, "threshold", PROCESS_DIR)
    save_step_image(th1_inv, "threshold_inverted", PROCESS_DIR)
    save_step_image(eroded_img, "eroded", PROCESS_DIR)
    save_step_image(dilated_img, "dilated", PROCESS_DIR)
    save_step_image(median_blurred, "median_blurred", PROCESS_DIR)
    save_step_image(closed_img, "closed", PROCESS_DIR)
    save_step_image(img_blur, "canny_blur", PROCESS_DIR)
    save_step_image(canny, "canny_edges", PROCESS_DIR)

def save_step_image(image, name, directory):
    save_path = os.path.join(directory, f'{name}.jpg')
    if cv.imwrite(save_path, image):
        print(f"成功保存处理步骤图像：{save_path}")
    else:
        print(f"错误：无法保存处理步骤图像到 {save_path}")

if __name__ == "__main__":
    main()